package com.glasses.manage.utils;

import org.apache.jasper.runtime.TldScanner;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.webapp.WebAppContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;

import javax.servlet.DispatcherType;
import java.lang.reflect.Field;
import java.util.EnumSet;
import java.util.Set;

/**
 * 标准spring 配置（java config） 嵌入式jetty9启动
 *
 * @author yy
 * @time 2015年01月22日
 */
public class JettyServer {
    private static final String DEFAULT_WEBAPP_PATH = "src/main/webapps";

    protected int port;

    protected String contextPath;

    protected Class<?> springRootConfiguration = null;

    protected Server server;
    protected WebAppContext context;

    public JettyServer(Class<?> springRootConfiguration) {
        this(8080, "/", springRootConfiguration);
    }

    public JettyServer(int port, String contextPath, Class<?> springRootConfiguration) {
        this.port = port;
        this.contextPath = contextPath;
        this.springRootConfiguration = springRootConfiguration;
        init(DEFAULT_WEBAPP_PATH);
    }

    public JettyServer(int port, String contextPath, String webAppPath, Class<?> springRootConfiguration) {
        this.port = port;
        this.contextPath = contextPath;
        this.springRootConfiguration = springRootConfiguration;
        init(webAppPath);
    }

    protected void init(String webAppPath) {
        /* fix jetty8.x, jetty 9.x can't load jstl library */
        Field f = null;
        try {
            f = TldScanner.class.getDeclaredField("systemUris");
            f.setAccessible(true);
            ((Set<?>) f.get(null)).clear();
            f.setAccessible(false);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        server = new Server();
        // 设置在JVM退出时关闭Jetty的钩子。
        server.setStopAtShutdown(true);
        //这是http的连接器
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(port);
        // 解决Windows下重复启动Jetty居然不报告端口冲突的问题.
        connector.setReuseAddress(true);
        server.setConnectors(new Connector[]{connector});
        context = new WebAppContext(webAppPath, contextPath);
        context.setDescriptor(webAppPath + "/WEB-INF/web.xml");
        // 设置webapp的位置
        context.setResourceBase(webAppPath);
        context.setClassLoader(Thread.currentThread().getContextClassLoader());
        server.setHandler(context);

        registerFilters();
        registersServlets();
        registerSpringContext();
    }

    protected void registersServlets() {
    }

    protected void registerFilters() {
        FilterHolder characterEncodingHolder = new FilterHolder(new CharacterEncodingFilter());
        characterEncodingHolder.setAsyncSupported(true);
        characterEncodingHolder.setInitParameter("encoding", "UTF-8");
        characterEncodingHolder.setInitParameter("forceEncoding", "true");
        EnumSet<DispatcherType> dispatches = EnumSet.of(DispatcherType.REQUEST);
        context.addFilter(characterEncodingHolder, "/*", dispatches);
    }


    //注入spring的配置信息
    protected void registerSpringContext() {
        if (null != springRootConfiguration) {
            AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
            rootContext.register(this.springRootConfiguration);
            context.addEventListener(new ContextLoaderListener(rootContext));
        }
    }

    public void start() throws Exception {
        if (server != null) {
            if (server.isStarting() || server.isStarted() || server.isRunning()) {
                return;
            }
        }
        server.start();
    }

    public void stop() throws Exception {
        if (server != null) {
            if (server.isRunning()) {
                server.stop();
            }
        }
    }

    public void join() throws InterruptedException {
        if (server != null) {
            server.join();
        }
    }

    //通过注解的方式注入spring配置
    @Configuration
    @ComponentScan("com.glasses.manage")
    @ImportResource(value = {"classpath:spring/*.xml"})
    public static class SpringRootConfiguration {
    }
}
